/*
 * fMatrix.c
 *
 *  Created on: Jun 26, 2013
 *      Author: koldar
 */

#include "fMatrix.h"
#include "main-tools.h"
#include "limits.h"

PfMatrix initFMatrix(int* N){
	PfMatrix result=(PfMatrix)malloc(sizeof(FMatrix));
	checkMalloc(result,"fMatrix.c:initFMatrix:1");
	result->N=N;
	result->minimum=0;
	result->minimumNumber=(*N*(*N-1))/2;
	result->matrix=(int**)malloc(*N*sizeof(int*));
	checkMalloc(result->matrix,"fMatrix.c:initFMatrix:2");
	int i;
	int j;
	for (i=0;i<*N;i++){
		result->matrix[i]=(int*)malloc(*N*sizeof(int));
		checkMalloc(result->matrix,"fMatrix.c:initFMatrix:3");
		for (j=(i+1);j<*N;j++){
			result->matrix[i][j]= 0;
		}
	}
	return result;
}


void freeFMatrix(PfMatrix obj){
	int i;
	for (i=0;i<*obj->N;i++){
		free(obj->matrix[i]);
	}
	free(obj->matrix);
	free(obj);
}


void setFMatrixValue(PedgeID pid,PfMatrix pmatrix,int value){
	if (value<pmatrix->minimum){//se value batte il vecchio minimo abbiamo un nuovo minimo
		pmatrix->minimum=value;
		pmatrix->minimumNumber=1;
		pmatrix->matrix[pid->i][pid->j]=value;
		return;
	}
	if (pmatrix->matrix[pid->i][pid->j]==pmatrix->minimum && value>pmatrix->minimum){//se stiamo modificando un minimo con un valore maggiore tolgo un minimo
		pmatrix->minimumNumber--;
		pmatrix->matrix[pid->i][pid->j]=value;
		if (pmatrix->minimumNumber==0){
			//printf("minimo %d in quanrtita %d valore da settare: %d valore in matrice: %d arco incriminiato:",pmatrix->minimum,pmatrix->minimumNumber,value,pmatrix->matrix[pid->i][pid->j]);printEdgeID(stdout,pid);printf("\n");
			//devo ricalcolare il minimo
			int i,j,tmp;
			tmp=INT_MAX;
			for (i=0;i<*pmatrix->N;i++){
				for (j=(i+1);j<*pmatrix->N;j++){
					if (pmatrix->matrix[i][j]<tmp){
						tmp=pmatrix->matrix[i][j];
						pmatrix->minimum=tmp;
						pmatrix->minimumNumber=1;
						continue;
					}
					if (pmatrix->matrix[i][j]==tmp){
						pmatrix->minimumNumber++;
					}
				}
			}
			//printf("quantita' finale: %d\n",pmatrix->minimumNumber);
		}
		return;
	}
	if (pmatrix->matrix[pid->i][pid->j]>pmatrix->minimum && value==pmatrix->minimum){//se non stiamo modificando un minimo ma lo impostiamo al valore minimo aggiungiamo un nuovo minimo
		pmatrix->minimumNumber++;
		pmatrix->matrix[pid->i][pid->j]=value;
		return;
	}
	pmatrix->matrix[pid->i][pid->j]=value;
}


int getFMatrixValue(PedgeID pid,PfMatrix pmatrix){
	return pmatrix->matrix[pid->i][pid->j];
}

void addFMatrixValue(PedgeID pid,PfMatrix pmatrix,int value){
	int realvalue=
		(pmatrix->matrix[pid->i][pid->j]+value)<0?
		0:
		pmatrix->matrix[pid->i][pid->j]+value;
	setFMatrixValue(pid,pmatrix,realvalue);
}


void printFMatrix(FILE* f,PfMatrix pmatrix){
	int i;
	int j;
	fprintf(f,"i\\j|");
	for (i=0;i<*pmatrix->N;i++){
		fprintf(f,"%3d|",(i+1));
	}
	fprintf(f,"\n");
	for (i=0;i<*pmatrix->N;i++){
		fprintf(f,"%3d|",(i+1));
		for (j=0;j<=i;j++){
			fprintf(f,"---|");
		}
		for (j=(i+1);j<*pmatrix->N;j++){
			fprintf(f,"%3d|",pmatrix->matrix[i][j]);
		}
		fprintf(f,"\n");
	}
}
